<script setup lang="ts">
import { Delete, Plus, Download } from "@element-plus/icons-vue"
import type {
  UploadProps,
  UploadUserFile,
  UploadInstance,
  UploadRawFile,
  FormInstance,
  FormRules,
  UploadFile
} from "element-plus"
import { ComponentPublicInstance, computed, nextTick, reactive, ref, watch } from "vue"
import { IUploadRequestData, UploadFileResponseData } from "@/api/files/types/files"
import dayjs from "@/utils/day"
import { useUserStore } from "@/store/modules/user"
import { IGetProjectIdAndNameResponseData } from "@/api/project/types/project"
import { getExtName, showPromptMessage } from "@/utils"
import Table from "../table/index.vue"
import { fileApplyApi } from "@/api/files"
import { IUserInfoData } from "@/api/login/types/login"
import { GetProjectIdAndNameList } from "@/api/project"
import { IGetDepartmentData } from "@/api/department/types/department"
import { getDepartmentIdAndNameList } from "@/api/department"
import { getItemListApi } from "@/api/necessary"
import { IGetFileResponseData } from "@/api/necessary/types/necessary"
import { useFullscreenLoading } from "@/hooks/useFullscreenLoading"
import { getToken } from "@/utils/cache/cookies"
import { downloadByUrl } from "@/utils"

const loading = ref(false)
const tableRef = ref()
const userStore = useUserStore()
const userInfo = userStore.userInfo as IUserInfoData
const ProjectData = ref<IGetProjectIdAndNameResponseData[]>([])
const btnLoading = ref(false)
const uploadFormRef = ref<FormInstance | null>(null)
const uploadData = ref<IUploadRequestData>({
  year: dayjs().year().toString(), // 立项年度
  projectId: undefined, // 资料类型
  projectName: "", // 培训项目名
  departmentId: userInfo.departmentId,
  note: "", // 备注
  isNecessary: 0,
  files: []
})
/** 获取项目列表-----*/
const getProjectDataList = () => {
  btnLoading.value = true
  GetProjectIdAndNameList({ name: "", departmentId: uploadData.value.departmentId })
    .then((res) => {
      ProjectData.value = res.data.list
    })
    .catch(() => {
      ProjectData.value = []
    })
    .finally(() => {
      btnLoading.value = false
    })
}
getProjectDataList()
/** 获取项目列表-----*/

/** 上传文件-----*/
const uploadRef = ref<UploadInstance>()
const fileList = ref<UploadUserFile[]>([])
const fileListNs = ref<UploadUserFile[][]>([])
const mySelect = ref()
const necessaryOptions = [
  {
    label: "补充资料",
    value: 0
  },
  {
    label: "必要资料",
    value: 1
  }
]
const uploadDialogVisible = ref(false)

const successData = ref<{ [key: string]: { file: UploadFile; note: string; success: boolean; url: string } }>({})
const handleSelectChange = () => {
  nextTick(() => {
    uploadData.value.projectName = mySelect.value.selected.currentLabel
  })
}
const handleUploadClick = async () => {
  getProjectDataList()
  uploadDialogVisible.value = true
}

const handleDeleteFile = (index: number) => {
  if (fileList.value[index]) uploadRef.value?.handleRemove(fileList.value[index] as UploadRawFile)
}
const handleUploadChange: UploadProps["onChange"] = (uploadFile, uploadFiles): void => {
  uploadFiles.forEach((file) => {
    if (!successData.value[file.uid]) {
      successData.value[file.uid] = {
        file,
        note: "",
        success: false,
        url: ""
      }
    }
  })
}
const handleUploadRemove: UploadProps["onRemove"] = (uploadFile): void => {
  delete successData.value[uploadFile.uid]
}

const handleUploadSuccess: UploadProps["onSuccess"] = (response: UploadFileResponseData, uploadFile): void => {
  successData.value[uploadFile.uid].success = true
  successData.value[uploadFile.uid].url = response.data.url
}

const allSuccess = computed(() => {
  const keys = Object.keys(successData.value)
  return keys.findIndex((key) => !successData.value[key].success) < 0
})

const fileApplyHanlder = useFullscreenLoading(
  () => {
    fileApplyApi(uploadData.value)
      .then(() => {
        uploadDialogVisible.value = false
        tableRef.value.getFilesDataList()
        showPromptMessage("success", "上传成功")
      })
      .catch(() => {
        uploadDialogVisible.value = false
      })
      .finally(() => {
        successData.value = {}
        uploadRef.value?.clearFiles()
        loading.value = false
      })
  },
  {
    text: "上传中"
  }
)

watch(allSuccess, (newV) => {
  if (newV) {
    buttonLoading.value = false
    const keys = Object.keys(successData.value)
    keys.forEach((key) => {
      const item = successData.value[key]
      uploadData.value.files.push({ name: item.file.name, note: item.note, url: item.url })
    })
    fileApplyHanlder()
  }
})
// 上传必须文件
const nsFormRef = ref<FormInstance | null>(null)
type types = Element | ComponentPublicInstance | null
const uploadNsRefs = ref<types[]>([])

const nsFormRules = computed(() => {
  const rules: FormRules = reactive({})
  necessaryFileList.value.forEach((file, index) => {
    rules[index] = {
      required: true,
      trigger: "change",
      message: `请选择${file.name}`
    }
  })

  return rules
})

const uploadFormRule: FormRules = {
  departmentId: [
    {
      required: true,
      trigger: "change",
      message: `请选择办学单位`
    }
  ],
  projectId: [
    {
      required: true,
      trigger: "change",
      message: `请选择项目`
    }
  ]
}
const FileDataSet = ref(new Map<string, UploadRawFile | undefined>())
const nsFileObj = reactive<Record<string, any>>({})
const successNsData = reactive<{ [key: string]: { file: UploadRawFile; note: string; success: boolean; url: string } }>(
  {}
)
const allNsSuccess = computed(() => {
  const keys = Object.keys(successNsData)
  return keys.findIndex((key) => !successNsData[key].success) < 0
})

const fileApplyNsHanlder = useFullscreenLoading(
  () => {
    fileApplyApi(uploadData.value)
      .then(() => {
        uploadDialogVisible.value = false
        tableRef.value.getFilesDataList()
        clearNsFile()
        showPromptMessage("success", "上传成功")
      })
      .catch(() => {
        uploadNsRefs.value.forEach((ref) => {
          const uploadRef = ref as UploadInstance
          uploadRef.clearFiles()
        })
      })
      .finally(() => {
        loading.value = false
      })
  },
  {
    text: "上传中"
  }
)

watch(allNsSuccess, (newV) => {
  if (newV) {
    buttonLoading.value = false
    const keys = Object.keys(successNsData)
    keys.forEach((key) => {
      const item = successNsData[key]
      uploadData.value.files.push({ name: item.file.name, note: item.note, url: item.url })
    })
    fileApplyNsHanlder()
  }
})

const DepartmentData = ref<IGetDepartmentData[]>([])
//#获取部门
const getDepartment = async () => {
  const result = await getDepartmentIdAndNameList({ name: "", departmentId: userInfo.departmentId })
  DepartmentData.value = result.data.list
}
getDepartment()

const handleBeforeUpload = (uploadFile: UploadRawFile, type: string) => {
  if (type === ".*") return true
  if (type.indexOf(getExtName(uploadFile.name)) < 0) {
    showPromptMessage("error", "文件格式不正确，请重新选择")
    return false
  }

  return true
}
const handleUploadNsChange = (uploadFile: UploadFile, index: string) => {
  FileDataSet.value.set(index, uploadFile.raw)
  nsFileObj[index] = uploadFile.name
}
const clearObj = (obj: { [key: string]: any }) => {
  const keys = Object.keys(obj)
  keys.forEach((key) => delete obj[key])
}
watch(
  FileDataSet,
  (newV) => {
    clearObj(successNsData)

    newV.forEach((val) => {
      if (val?.uid) {
        successNsData[val.uid] = {
          file: val,
          note: "",
          success: false,
          url: ""
        }
      }
    })
  },
  { deep: true }
)
const handleUploadNsSuccess: UploadProps["onSuccess"] = (response: UploadFileResponseData, uploadFile): void => {
  if (response.data) {
    successNsData[uploadFile.uid].success = true
    successNsData[uploadFile.uid].url = response.data.url
  }
}
const buttonLoading = ref(false)
/** 上传文件-----*/
const handleConfirmUpload = () => {
  buttonLoading.value = true
  if (uploadData.value.isNecessary) {
    nsFormRef.value?.validate((valid: boolean) => {
      if (valid) {
        uploadNsRefs.value.forEach((ref) => {
          const uploadRef = ref as UploadInstance
          uploadRef.submit()
        })
      } else {
        return false
      }
    })
  } else {
    uploadFormRef.value?.validate((valid) => {
      if (valid) {
        uploadRef.value?.submit()
      } else {
        return false
      }
    })
  }
}

const resetUploadForm = () => {
  uploadData.value.note = ""
  uploadData.value.projectId = undefined
  uploadData.value.files = []
  uploadData.value.projectName = ""
  uploadData.value.departmentId = userInfo.departmentId
  uploadRef.value?.clearFiles()
  uploadFormRef.value?.resetFields()
  clearNsFile()
}

//必要文件列表
const necessaryFileList = ref<IGetFileResponseData[]>([])
watch([() => uploadData.value.departmentId], () => {
  uploadData.value.projectId = undefined
  getProjectDataList()
  clearObj(nsFileObj)
  necessaryFileList.value = []
  uploadRef.value?.clearFiles()
  uploadNsRefs.value.forEach((ns) => (ns as UploadInstance)?.clearFiles())
})

watch(
  [() => uploadData.value.isNecessary, () => uploadData.value.departmentId, () => uploadData.value.projectId],
  (newV) => {
    if (newV[0] && newV[1] && newV[2]) {
      uploadData.value.departmentId &&
        getItemListApi(uploadData.value.departmentId).then((res) => {
          necessaryFileList.value = res.data.list
        })
    }
  }
)

const clearNsFile = () => {
  FileDataSet.value.clear()
  nsFileObj.value = {}
  uploadNsRefs.value.forEach((u) => (u as UploadInstance)?.clearFiles())
  necessaryFileList.value = []
  nsFormRef.value?.resetFields()
}

const download = (row: IGetFileResponseData) => {
  downloadByUrl(row.fileTemplateUrl, row.fileTemplateFilename)
}

watch(
  [() => uploadData.value.departmentId, () => uploadData.value.projectId, () => uploadData.value.isNecessary],
  (newV) => {
    const has = newV.findIndex((v) => !v)
    if (has >= 0) {
      //清空
      clearNsFile()
    }
  }
)
</script>

<template>
  <div v-loading="loading" element-loading-text="加载中">
    <el-card shadow="never">
      <el-button type="primary" @click="handleUploadClick"
        ><el-icon><Plus /></el-icon>上传资料</el-button
      >
    </el-card>
    <!--    上传文件弹窗 -->
    <el-dialog align-center @closed="resetUploadForm" v-model="uploadDialogVisible" title="上传文件" width="600px">
      <el-form :model="uploadData" ref="uploadFormRef" label-width="80" inline-form :rules="uploadFormRule">
        <el-row :gutter="10">
          <el-col :span="12">
            <el-form-item label="立项年度" prop="year">
              <el-date-picker
                :clearable="false"
                style="width: 100%"
                v-model="uploadData.year"
                type="year"
                placeholder="立项年度"
                value-format="YYYY"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="userInfo.authority === '2'">
            <el-form-item prop="departmentId" label="办学单位">
              <el-select
                ref="mySelect"
                filterable
                @change="handleSelectChange"
                v-model="uploadData.departmentId"
                placeholder="选择办学单位"
              >
                <el-option v-for="item in DepartmentData" :key="item.id" :label="item.name" :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="12">
            <el-form-item prop="projectId" label="培训项目">
              <el-select
                :disabled="!uploadData.departmentId"
                style="width: 100%"
                ref="mySelect"
                filterable
                @change="handleSelectChange"
                v-model="uploadData.projectId"
                placeholder="选择培训项目"
              >
                <el-option v-for="item in ProjectData" :key="item.id" :label="item.name" :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="12">
            <el-form-item label="资料类型">
              <el-select ref="mySelect" v-model="uploadData.isNecessary" placeholder="是否为必须文件">
                <el-option v-for="item in necessaryOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="24">
            <el-form-item label="备注信息"> <el-input v-model="uploadData.note" placeholder="备注信息" /> </el-form-item
          ></el-col>
        </el-row>
      </el-form>

      <div v-show="!uploadData.isNecessary">
        <div class="mt-2">
          <el-upload
            :action="'/api/v2/file/upload?year=' + uploadData.year + '&projectName=' + uploadData.projectName"
            :on-change="handleUploadChange"
            :on-remove="handleUploadRemove"
            :on-success="handleUploadSuccess"
            ref="uploadRef"
            :show-file-list="false"
            v-model:file-list="fileList"
            multiple
            :auto-upload="false"
            :headers="{ token: getToken() }"
          >
            <el-button type="primary"
              ><el-icon><Plus /></el-icon>选择文件</el-button
            >
          </el-upload>
        </div>
        <div class="file-list mt-2 max-h-96 overflow-y-auto">
          <ul>
            <li dfy class="bg-gray-100 mb-2 p-2 rounded" v-for="(file, index) in fileList" :key="file.uid">
              <div class="flex w-full items-center justify-between">
                <div dfy>
                  <span>{{ file.name }}</span>
                  <el-input
                    :disabled="successData[file.uid].success"
                    v-if="file.uid && successData[file.uid]"
                    class="mt-2"
                    style="width: 400px"
                    placeholder="添加备注信息"
                    v-model="successData[file.uid].note"
                  />
                </div>
                <div>
                  <el-button @click="handleDeleteFile(index)" circle type="danger">
                    <el-icon><Delete /></el-icon>
                  </el-button>
                </div>
              </div>
              <el-progress v-if="fileList[index]" :percentage="fileList[index].percentage" />
            </li>
          </ul>
        </div>
      </div>

      <!-- 上传必要文件 -->
      <div v-show="uploadData.isNecessary" class="mt-5">
        <el-form label-position="top" ref="nsFormRef" :rules="nsFormRules" :model="nsFileObj" label-width="130px">
          <el-form-item :prop="index + ''" :label="item.name" v-for="(item, index) in necessaryFileList" :key="item.id">
            <div class="flex w-full items-center justify-between">
              <el-input
                v-model="nsFileObj[index + '']"
                class="mr-2"
                disabled
                :placeholder="'文件名自动填充' + '(文件类型：' + item.type + ')'"
              />
              <el-button @click="download(item)" v-if="item.fileTemplateUrl" class="mr-1" type="success"
                ><el-icon><Download /></el-icon>下载模板</el-button
              >
              <el-upload
                :action="'/api/v2/file/upload?year=' + uploadData.year + '&projectName=' + uploadData.projectName"
                :ref="(el) => (uploadNsRefs[index] = el)"
                :before-upload="(uploadFile) => handleBeforeUpload(uploadFile, item.type)"
                :on-change="(uploadFile) => handleUploadNsChange(uploadFile, index + '')"
                :on-success="handleUploadNsSuccess"
                class="flex justify-center items-center"
                :accept="item.type"
                :show-file-list="false"
                :auto-upload="false"
                v-model:file-list="fileListNs[index]"
                :headers="{ token: getToken() }"
              >
                <el-button type="primary"
                  ><el-icon><Plus /></el-icon>选择文件</el-button
                >
              </el-upload>
            </div>
            <div class="w-full mt-2">
              <el-progress
                v-if="fileListNs[index] && fileListNs[index][0]"
                :percentage="fileListNs[index][0].percentage"
              />
            </div>
          </el-form-item>
          <!-- <el-form-item prop="scan" label="培训方案扫描盖章页">
            <div class="flex w-full items-center justify-between">
              <el-input v-model="nsFileObj.scan" class="mr-2" disabled placeholder="文件名自动填充" />
              <el-upload
                :action="
                  '/api/v2/file/upload?year=' +
                  uploadData.year +
                  '&projectName=' +
                  uploadData.projectName +
                  '&uploaderId=' +
                  userInfo.id
                "
                :on-change="handleUploadSCANChange"
                :on-remove="handleUploadNsRemove"
                :on-success="handleUploadNsSuccess"
                class="flex justify-center items-center"
                :ref="(el) => (uploadNsRefs[1] = el)"
                :show-file-list="false"
                v-model:file-list="scanFileList"
                :auto-upload="false"
              >
                <el-button type="primary"
                  ><el-icon><Plus /></el-icon>选择文件</el-button
                >
              </el-upload>
            </div>
          </el-form-item>
          <el-form-item prop="elec" label="培训方案电子版">
            <div class="flex w-full items-center justify-between">
              <el-input v-model="nsFileObj.elec" class="mr-2" disabled placeholder="文件名自动填充" />
              <el-upload
                :action="'/api/v2/file/upload?year=' + uploadData.year + '&projectName=' + uploadData.projectName"
                :on-change="handleUploadElecChange"
                :on-remove="handleUploadNsRemove"
                :on-success="handleUploadNsSuccess"
                class="flex justify-center items-center"
                :ref="(el) => (uploadNsRefs[2] = el)"
                :show-file-list="false"
                v-model:file-list="elecFileList"
                :auto-upload="false"
              >
                <el-button type="primary"
                  ><el-icon><Plus /></el-icon>选择文件</el-button
                >
              </el-upload>
            </div>
          </el-form-item>
          <el-form-item prop="table" label="非学历教育信息表">
            <div class="flex w-full items-center justify-between">
              <el-input v-model="nsFileObj.table" class="mr-2" disabled placeholder="文件名自动填充" />
              <el-upload
                :action="'/api/v2/file/upload?year=' + uploadData.year + '&projectName=' + uploadData.projectName"
                :on-change="handleUploadTableChange"
                :on-remove="handleUploadNsRemove"
                :on-success="handleUploadNsSuccess"
                class="flex justify-center items-center"
                :ref="(el) => (uploadNsRefs[3] = el)"
                :show-file-list="false"
                v-model:file-list="tableFileList"
                :auto-upload="false"
              >
                <el-button type="primary"
                  ><el-icon><Plus /></el-icon>选择文件</el-button
                >
              </el-upload>
            </div>
          </el-form-item> -->
        </el-form>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="handleConfirmUpload"> 上传 </el-button>
          <el-button @click="uploadDialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>

    <Table ref="tableRef" />
  </div>
</template>

<style scoped lang="scss">
.file-list::-webkit-scrollbar {
  width: 2px;
  background-color: rgba(255, 255, 255, 0.5);
}
.file-list::-webkit-scrollbar-thumb {
  background-color: #e5e7eb;
}
</style>
